package com.plter.media
{
	import com.codeazur.as3swf.SWF;
	import com.codeazur.as3swf.SWFData;
	import com.codeazur.as3swf.data.SWFScene;
	import com.codeazur.as3swf.data.SWFSymbol;
	import com.codeazur.as3swf.tags.TagDefineSceneAndFrameLabelData;
	import com.codeazur.as3swf.tags.TagDefineSound;
	import com.codeazur.as3swf.tags.TagDoABC;
	import com.codeazur.as3swf.tags.TagEnd;
	import com.codeazur.as3swf.tags.TagFileAttributes;
	import com.codeazur.as3swf.tags.TagSetBackgroundColor;
	import com.codeazur.as3swf.tags.TagShowFrame;
	import com.codeazur.as3swf.tags.TagSymbolClass;
	
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SampleDataEvent;
	import flash.media.ID3Info;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundLoaderContext;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;
	import flash.sampler.startSampling;
	import flash.system.Capabilities;
	import flash.utils.ByteArray;



	[Event(name="complete", type="flash.events.Event")]
	[Event(name="open", type="flash.events.Event")]
	[Event(name="init", type="flash.events.Event")]
	[Event(name="progress", type="flash.events.ProgressEvent")]
	[Event(name="sampleData", type="flash.events.SampleDataEvent")]
	[Event(name="ioError", type="flash.events.IOErrorEvent")]

	public class PSound extends EventDispatcher
	{

		[Embed(source="abcdata.abc", mimeType="application/octet-stream")]
		protected var AbcData:Class;

		private var sound:Sound;

		public function PSound()
		{

		}


		/**
		 * 以二进制形式加载mp3文件
		 * @param sound	mp3声音文件数据
		 */
		public function loadBytes(mp3:ByteArray):void
		{

			try
			{
				var swfData:ByteArray=createSwfBytesWithSoundBytes(mp3);
				
				var loader:Loader=new Loader;
				loader.contentLoaderInfo.addEventListener(Event.INIT, bytesSoundInitHandler);
				loader.loadBytes(swfData);

				swfData.length=0;
				mp3.length=0;
			}
			catch (error:Error)
			{
				mp3.length=0;
				throw new PSoundTypeError("Unsupported sound type");
			}
		}

		public function load(stream:URLRequest, context:SoundLoaderContext=null):void
		{
			if (sound != null)
			{
				sound.removeEventListener(Event.COMPLETE, soundEventHandler);
				sound.removeEventListener(Event.OPEN, soundEventHandler);
				sound.removeEventListener(Event.ID3, soundEventHandler);
				sound.removeEventListener(IOErrorEvent.IO_ERROR, soundEventHandler);
				sound.removeEventListener(ProgressEvent.PROGRESS, soundEventHandler);
				sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, soundEventHandler);
			}


			sound=new Sound;
			sound.addEventListener(Event.COMPLETE, soundEventHandler);
			sound.addEventListener(Event.OPEN, soundEventHandler);
			sound.addEventListener(Event.ID3, soundEventHandler);
			sound.addEventListener(IOErrorEvent.IO_ERROR, soundEventHandler);
			sound.addEventListener(ProgressEvent.PROGRESS, soundEventHandler);
			sound.addEventListener(SampleDataEvent.SAMPLE_DATA, soundEventHandler);

			sound.load(stream, context);
		}

		public function play(startTime:Number=0, loops:int=0, sndTransform:SoundTransform=null):SoundChannel
		{
			if (sound != null)
			{
				return sound.play(startTime, loops, sndTransform);
			}
			return null;
		}

		public function get bytesLoaded():uint
		{
			if (sound != null)
			{
				return sound.bytesLoaded;
			}
			return 0;
		}

		public function get bytesTotal():uint
		{
			if (sound != null)
			{
				return sound.bytesTotal;
			}
			return 0;
		}

		public function get id3():ID3Info
		{
			if (sound != null)
			{
				return sound.id3;
			}
			return null;
		}

		public function get isBuffering():Boolean
		{
			if (sound != null)
			{
				return sound.isBuffering;
			}
			return false;
		}

		public function get length():Number
		{
			if (sound != null)
			{
				return sound.length;
			}
			return 0;
		}

		public function get url():String
		{
			if (sound != null)
			{
				return sound.url;
			}
			return "";
		}

		public function close():void
		{
			if (sound != null)
			{
				sound.close();
			}
		}

		public function extract(target:ByteArray, length:Number, startPosition:Number=-1):Number
		{
			if (sound != null)
			{
				return sound.extract(target, length, startPosition);
			}
			return 0;
		}

		private function soundEventHandler(event:Event):void
		{
			dispatchEvent(event);
		}

		private function bytesSoundInitHandler(event:Event):void
		{
			event.target.removeEventListener(Event.INIT, bytesSoundInitHandler);

			var SoundClass:Class=LoaderInfo(event.target).applicationDomain.getDefinition("MP3Wrapper_soundClass") as Class;
			sound=new SoundClass as Sound;

			dispatchEvent(new Event(Event.COMPLETE));

			try
			{
				event.target.loader.unloadAndStop(true);
			}
			catch (error:Error)
			{
				event.target.loader.unload();
			}
		}
		
		private function createSwfBytesWithSoundBytes(mp3:ByteArray):ByteArray{
			// Create an empty SWF
			// Defaults to v10, 550x400px, 50fps, one frame (works fine for us)
			var swf:SWF=new SWF();
			
			// Add FileAttributes tag
			// Defaults: as3 true, all other flags false (works fine for us)
			swf.tags.push(new TagFileAttributes());
			
			// Add SetBackgroundColor tag
			// Default: white background (works fine for us)
			swf.tags.push(new TagSetBackgroundColor());
			
			// Add DefineSceneAndFrameLabelData tag
			// (with the only entry being "Scene 1" at offset 0)
			var defineSceneAndFrameLabelData:TagDefineSceneAndFrameLabelData=new TagDefineSceneAndFrameLabelData();
			defineSceneAndFrameLabelData.scenes.push(new SWFScene(0, "Scene 1"));
			swf.tags.push(defineSceneAndFrameLabelData);
			
			// Add DefineSound tag
			// The ID is 1, all other parameters are automatically
			// determined from the mp3 itself.
			swf.tags.push(TagDefineSound.createWithMP3(1, mp3));
			
			// Add DoABC tag
			// Contains the AS3 byte code for the document class and the
			// class definition for the embedded sound
			swf.tags.push(TagDoABC.create(new AbcData as ByteArray));
			
			// Add SymbolClass tag
			// Specifies the document class and binds the sound class
			// definition to the embedded sound
			var symbolClass:TagSymbolClass=new TagSymbolClass();
			symbolClass.symbols.push(SWFSymbol.create(1, "MP3Wrapper_soundClass"));
			symbolClass.symbols.push(SWFSymbol.create(0, "MP3Wrapper"));
			swf.tags.push(symbolClass);
			
			// Add ShowFrame tag
			swf.tags.push(new TagShowFrame);
			
			// Add End tag
			swf.tags.push(new TagEnd);
			
			// Publish the SWF
			var swfData:SWFData=new SWFData();
			swf.publish(swfData);
			
			return swfData;
		}
	}
}

